package com.artup.util.excel;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSONArray;
import com.artup.common.Constants;
import com.artup.pojo.Address;
import com.artup.pojo.Invoice;
import com.artup.pojo.Region;
import com.artup.util.CommonUtils;
import com.artup.util.cache.RedisUtils;
import com.artup.util.date.DateUtil;

import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.Jedis;

@Slf4j
public class OrderExport extends AbstractExport {
	private static Jedis jedis = RedisUtils.getJedis();
	
//	private String filePrefix;	// 文件前缀
//	private String fileSuffix;		// 文件扩展名
	private String excelFileName;	// 文件名
//	private Date exportTime;	// 导出时间
//	private WritableWorkbook writableWorkbook;	// 可写入的“工作簿”
	private WritableSheet writableSheet;		// 可写入的“工作表”
	private int rowIndex = 0;	// 行索引
 
	public OrderExport() throws Exception {
		String filePrefix = "test_" + DateUtil.getDateFormat(new Date(), "yyyyMMddHHmm");
		String fileSuffix = "xls";
		excelFileName = filePrefix + "." + fileSuffix;
	}
	
	public void excelGenerator(List<Map<String, Object>> orderList, String excelFileName) {
		if(StringUtils.isNotBlank(excelFileName)){
			this.excelFileName = excelFileName + ".xls";
		} else {
			String filePrefix = DateUtil.getDateFormat(new Date(), "yyyyMMddHHmm");
			String fileSuffix = "xls";
			this.excelFileName = filePrefix + "." + fileSuffix;
		}
		
		HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
		response.setContentType("Application/msexcel");
		response.setCharacterEncoding("UTF-8");
		response.setHeader("Content-disposition", "attachment; filename="
				+ this.excelFileName);
		
		OutputStream outputStream = null;
		try {
			outputStream = response.getOutputStream();
		} catch (IOException e) {
			log.error("获取 HTTP Servlet 输出流 - 失败！", e);
		}
		
		WritableWorkbook writableWorkbook = null;	// 可写入的“工作簿”
		
		if(null != outputStream){
			try {
				writableWorkbook = Workbook.createWorkbook(outputStream);
			} catch (IOException e) {
				log.error("创建【工作薄】 - 失败！", e);
			}
		}
		
		writableSheet = writableWorkbook.createSheet("订单列表", 0);		// 创建第一个“工作表”
		
		try {
			this.setSheetContent(orderList);
		} catch (WriteException e) {
			log.error("设置【数据表】内容 - 失败！", e);
		}

		try {
			writableWorkbook.write();
		} catch (IOException e) {
			log.error("执行向工作薄中写入操作 - 失败！", e);
		}
		
		try {
			writableWorkbook.close();
		} catch (WriteException | IOException e) {
			log.error("关闭【工作薄】 - 失败！", e);
		}
		
		try {
			outputStream.flush();
		} catch (IOException e) {
			log.error("刷新 HTTP Servlet 输出流 - 失败！", e);
		}
		
		if(null != outputStream) {
			try {
				outputStream.close();
			} catch (IOException e) {
				log.error("关闭 HTTP Servlet 输出流 - 失败！", e);
			}
		}
	}

	/**
	 * 向数据表中写入内容
	 * @param orderList
	 * @throws WriteException
	 */
	private void setSheetContent(List<Map<String, Object>> orderList)
			throws WriteException {
		List<Map<String, Object>> sheetTitleList = this.setSheetTitle();

		// 标题
		Label toolTitleLabel = new Label(0, rowIndex, "订单列表（" + DateUtil.getDateFormat(new Date(), "yyyy-MM-dd HH:mm") + "）", formatTitle1);
		writableSheet.addCell(toolTitleLabel);
		writableSheet.mergeCells(0, rowIndex, sheetTitleList.size() - 1, 0);
		rowIndex++;

		// 写表头
		this.writeSheetContent(writableSheet, sheetTitleList);
		rowIndex++;

		String regions = jedis.get(Constants.CACHE_TYPE_REGION_LIST);
		
		for (int i = 0; i < orderList.size(); i++) {
			Map<String, Object> orderMap = orderList.get(i);
			int detailCount = 1;
			if (detailCount > 1) {
				writableSheet.mergeCells(1, rowIndex, 1, rowIndex + detailCount -1);
			}
			
			Label gridLabel = null;		// 单元格
			
			// 订单号
			if(null == orderMap.get("orderCode")) {
				gridLabel = new Label(0, rowIndex, "", contentStyle);
			} else {
				gridLabel = new Label(0, rowIndex, orderMap.get("orderCode").toString(), contentStyle);
			}
			writableSheet.addCell(gridLabel);
			
			// 商户订单号
			if(null == orderMap.get("tradeCode"))
				gridLabel = new Label(1, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(1, rowIndex, String.valueOf(orderMap.get("tradeCode")), contentStyle);
			writableSheet.addCell(gridLabel);
			
			// 订单来源
			if(null == orderMap.get("clientCode"))
				gridLabel = new Label(2, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(2, rowIndex, String.valueOf(orderMap.get("clientCode")), contentStyle);
			writableSheet.addCell(gridLabel);
			
			// 下单时间
			if(null == orderMap.get("createTime")) {
				gridLabel = new Label(3, rowIndex, "", contentStyle);
			} else {
				gridLabel = new Label(3, rowIndex, String.valueOf(orderMap.get("createTime")), contentStyle);
			}
			writableSheet.addCell(gridLabel);
			
			// 付款时间	
			if(null == orderMap.get("payment")) {
				gridLabel = new Label(4, rowIndex, "", contentStyle);
			} else {
				@SuppressWarnings("unchecked")
				Map<String, Object> paymentMap = (Map<String, Object>) orderMap.get("payment");
				
				if(null == paymentMap.get("payFinishTime")) {
					gridLabel = new Label(4, rowIndex, "", contentStyle);
				} else {
					gridLabel = new Label(4, rowIndex, paymentMap.get("payFinishTime").toString(), contentStyle);
				}
			}
			writableSheet.addCell(gridLabel);
			
			// 审核时间	
			if(null == orderMap.get("checkTime")) 
				gridLabel = new Label(5, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(5, rowIndex, String.valueOf(orderMap.get("checkTime")), contentStyle);
			writableSheet.addCell(gridLabel);
			
			// 优惠券编码
			if(null == orderMap.get("couponCode"))
				gridLabel = new Label(6, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(6, rowIndex, String.valueOf(orderMap.get("couponCode")), contentStyle);
			writableSheet.addCell(gridLabel);
			
			// 订单状态
			if(null == orderMap.get("statusName"))
				gridLabel = new Label(7, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(7, rowIndex, String.valueOf(orderMap.get("statusName")), contentStyle);
			writableSheet.addCell(gridLabel);

			// 审核状态
			if(null == orderMap.get("checkStatusName"))
				gridLabel = new Label(8, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(8, rowIndex, String.valueOf(orderMap.get("checkStatusName")), contentStyle);
			writableSheet.addCell(gridLabel);

			// 地址
			if(null == orderMap.get("address")) {
				gridLabel = new Label(11, rowIndex, "", contentStyle);
				gridLabel = new Label(12, rowIndex, "", contentStyle);
				gridLabel = new Label(13, rowIndex, "", contentStyle);
				gridLabel = new Label(14, rowIndex, "", contentStyle);
				gridLabel = new Label(15, rowIndex, "", contentStyle);
				gridLabel = new Label(16, rowIndex, "", contentStyle);
			} else {
				Address address = (Address) orderMap.get("address");
				
				if(StringUtils.isEmpty(address.getName())) {
					gridLabel = new Label(11, rowIndex, "", contentStyle);
				} else {
					gridLabel = new Label(11, rowIndex, address.getName(), contentStyle);
				}
				writableSheet.addCell(gridLabel);

				if(StringUtils.isEmpty(address.getMobileCode())){
					gridLabel = new Label(12, rowIndex, "", contentStyle);
				} else {
					gridLabel = new Label(12, rowIndex, address.getMobileCode(), contentStyle);
				}
				writableSheet.addCell(gridLabel);

				if(CommonUtils.isNotEmpty(regions)) {
					List<Region> regionList = JSONArray.parseArray(regions, Region.class);
					for(Region region : regionList) {
						if(address.getProvinceId() == region.getId()){
							gridLabel = new Label(13, rowIndex, region.getName(), contentStyle);
							
							writableSheet.addCell(gridLabel);
						}
					}
					for(Region region : regionList) {
						if(address.getCityId() == region.getId()){
							gridLabel = new Label(14, rowIndex, region.getName(), contentStyle);
							
							writableSheet.addCell(gridLabel);
						}
					}
					for(Region region : regionList) {
						if(address.getDistrictId() == region.getId()){
							gridLabel = new Label(15, rowIndex, region.getName(), contentStyle);
							
							writableSheet.addCell(gridLabel);
						}
					}
					
					if(StringUtils.isEmpty(address.getDetail())) {
						gridLabel = new Label(16, rowIndex, "", contentStyle);
					} else {
						gridLabel = new Label(16, rowIndex, address.getDetail(), contentStyle);
					}
					writableSheet.addCell(gridLabel);
				}
			}
			
			// 商品类型s
			if(null == orderMap.get("worksTypeNames"))
				gridLabel = new Label(17, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(17, rowIndex, String.valueOf(orderMap.get("worksTypeNames")), contentStyle);
			writableSheet.addCell(gridLabel);

			// 商品尺寸s
			if(null == orderMap.get("worksSizes"))
				gridLabel = new Label(18, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(18, rowIndex, String.valueOf(orderMap.get("worksSizes")), contentStyle);
			writableSheet.addCell(gridLabel);

			// 商品数量s
			if(null == orderMap.get("worksQuantities"))
				gridLabel = new Label(19, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(19, rowIndex, String.valueOf(orderMap.get("worksQuantities")), contentStyle);
			writableSheet.addCell(gridLabel);

			// 商品单价s
			if(null == orderMap.get("worksPrices"))
				gridLabel = new Label(20, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(20, rowIndex, String.valueOf(orderMap.get("worksPrices")), contentStyle);
			writableSheet.addCell(gridLabel);

			// 商品 SKU 编号s
			if(null == orderMap.get("worksSkuCodes"))
				gridLabel = new Label(21, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(21, rowIndex, String.valueOf(orderMap.get("worksSkuCodes")), contentStyle);
			writableSheet.addCell(gridLabel);

			// 商品颜色s
			if(null == orderMap.get("worksColors"))
				gridLabel = new Label(22, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(22, rowIndex, String.valueOf(orderMap.get("worksColors")), contentStyle);
			writableSheet.addCell(gridLabel);
			
			// 框型
			if(null == orderMap.get("worksShapes"))
				gridLabel = new Label(23, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(23, rowIndex, String.valueOf(orderMap.get("worksShapes")), contentStyle);
			writableSheet.addCell(gridLabel);

			// 总优惠金额
			if(null == orderMap.get("totalPrice"))
				gridLabel = new Label(24, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(24, rowIndex, String.valueOf(orderMap.get("totalPrice")), contentStyle);
			writableSheet.addCell(gridLabel);

			// 总优惠金额
			if(null == orderMap.get("totalDiscount"))
				gridLabel = new Label(25, rowIndex, "", contentStyle);
			else
				gridLabel = new Label(25, rowIndex, String.valueOf(orderMap.get("totalDiscount")), contentStyle);
			writableSheet.addCell(gridLabel);

			// 支付
			if(null == orderMap.get("payment")) {
				gridLabel = new Label(26, rowIndex, "", contentStyle);
				gridLabel = new Label(27, rowIndex, "", contentStyle);
			} else {
				@SuppressWarnings("unchecked")
				Map<String, Object> paymentMap = (Map<String, Object>) orderMap.get("payment");
				
				// 实收金额
				if(null == paymentMap.get("payTotalPrice")) {
					gridLabel = new Label(26, rowIndex, "", contentStyle);
				} else {
					gridLabel = new Label(26, rowIndex, String.valueOf(paymentMap.get("payTotalPrice")), contentStyle);
				}
				writableSheet.addCell(gridLabel);

				// 支付方式
				if(null == paymentMap.get("payTypeName")) {
					gridLabel = new Label(27, rowIndex, "", contentStyle);
				} else {
					gridLabel = new Label(27, rowIndex, String.valueOf(paymentMap.get("payTypeName")), contentStyle);
				}
				writableSheet.addCell(gridLabel);
			}
			
			// 商品 SKU 编号s
			if(null == orderMap.get("invoice")){
				gridLabel = new Label(29, rowIndex, "", contentStyle);
				gridLabel = new Label(30, rowIndex, "", contentStyle);
			} else {
				Invoice invoice = (Invoice) orderMap.get("invoice");
				
				if(StringUtils.isBlank(invoice.getTitle())) {
					gridLabel = new Label(29, rowIndex, "", contentStyle);
				} else {
					gridLabel = new Label(29, rowIndex, String.valueOf(invoice.getTitle()), contentStyle);
				}
				writableSheet.addCell(gridLabel);

				if(StringUtils.isBlank(invoice.getContent())) {
					gridLabel = new Label(30, rowIndex, "", contentStyle);
				} else {
					gridLabel = new Label(30, rowIndex, String.valueOf(invoice.getContent()), contentStyle);
				}
				writableSheet.addCell(gridLabel);
			}
			
			rowIndex = rowIndex + detailCount - 1;

			rowIndex++;
		}
	}

	private List<Map<String, Object>> setSheetTitle() {
		List<Map<String, Object>> sheetTitleList = new ArrayList<Map<String, Object>>();
		
		Map<String, Object> sheetTitleMap = new HashMap<String, Object>();
		
		sheetTitleMap.put("title", "订单号");
		sheetTitleMap.put("width", 30);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "商户订单号");
		sheetTitleMap.put("width", 35);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "订单来源");
		sheetTitleMap.put("width", 15);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "下单时间");
		sheetTitleMap.put("width", 18);
		sheetTitleList.add(sheetTitleMap);

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "付款时间");
		sheetTitleMap.put("width", 18);
		sheetTitleList.add(sheetTitleMap);

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "审核时间");
		sheetTitleMap.put("width", 18);
		sheetTitleList.add(sheetTitleMap);

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "券号");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "状态");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "订单审核");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "商家备注");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "确认到款 ");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "收货人姓名");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "收货人电话");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "省份");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "地市");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "区县");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "详细地址");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "商品类型");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "商品尺寸");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "商品数量");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "商品单价");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "商品 SKU");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "商品颜色");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "框型");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "订单金额");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);

		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "优惠金额");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "实收金额");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "支付方式");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "优惠名称");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "发票抬头");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "发票内容");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "开票时间");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "发票号");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "物流号");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "物流公司");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "售后情况");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "售后原因");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "售后办理时间");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "退款金额");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		sheetTitleMap = new HashMap<String, Object>();
		sheetTitleMap.put("title", "图片类型");
		sheetTitleMap.put("width", 20);
		sheetTitleList.add(sheetTitleMap);
		
		return sheetTitleList;
	}

	/**
	 * 向数据表中写入内容
	 * @param writableSheet
	 * @param titleList
	 */
	private void writeSheetContent(WritableSheet writableSheet, List<Map<String, Object>> titleList) {
		if(CommonUtils.isEmpty(titleList))
			return;
		
		for (int index = 0; index < titleList.size(); index++) {
			Map<String, Object> titleMap = titleList.get(index);
			
			if(CommonUtils.isEmpty(titleMap))
				continue;
			
			if(null != titleMap.get("title")) {
				Label label = new Label(index, rowIndex, titleMap.get("title")
						.toString(), titleStyle);
				try {
					writableSheet.addCell(label);
				} catch (WriteException e) {
					log.error("向【工作表】中添加内容 - 失败！", e);
				}
			}
			
			if(null != titleMap.get("width"))
				writableSheet.setColumnView(index, Integer.parseInt(titleMap.get("width").toString()));
		}
	}

	public Date getExportTime() {
		return exportTime;
	}

	public void setExportTime(Date exportTime) {
		this.exportTime = exportTime;
	}

}
